#include "texture.h"
#include "direct3d9.h"
#include "gmemory.h"

// const char* g_temp_memory = new char[2048 * 2048 * 4];

TextureQuad::TextureQuad() : x(0), y(0), width(0), height(0) {
}

void TextureQuad::setXY(int x, int y) {
    this->x = x;
    this->y = y;
}

void TextureQuad::setSize(int width, int height) {
    this->width = width;
    this->height = height;
}


void TextureQuad::setRect(int x, int y, int width, int height) {

    vertexs[0].tx = vertexs[3].tx = x * 1.0f / this->width;
    vertexs[0].ty = vertexs[1].ty = y * 1.0f / this->height;
    vertexs[1].tx = vertexs[2].tx = (x + width) * 1.0f / this->width;
    vertexs[2].ty = vertexs[3].ty = (y + height) * 1.0f / this->height;

    float x1, y1, x2, y2;
    x1 = 0.0f; // -_anX * _w * _scaleX;
    y1 = 0.0f; // -_anY * _h * _scaleY;
    x2 = width; // (_w - _anX * _w)* _scaleX;
    y2 = height; // (_h - _anY * _h)* _scaleY;

    vertexs[0].x = x1 + this->x; vertexs[0].y = y1 + this->y;
    vertexs[1].x = x2 + this->x; vertexs[1].y = y1 + this->y;
    vertexs[2].x = x2 + this->x; vertexs[2].y = y2 + this->y;
    vertexs[3].x = x1 + this->x; vertexs[3].y = y2 + this->y;

//     if (_rotate != 0.0f) {
//         float sint, cost;
//         cost = cosf(_rotate * PI / 180);
//         sint = sinf(_rotate * PI / 180);
// 
//         vertexs[0].x = x1 * cost - y1 * sint + this->x;
//         vertexs[0].y = x1 * sint + y1 * cost + this->y;
// 
//         vertexs[1].x = x2 * cost - y1 * sint + this->x;
//         vertexs[1].y = x2 * sint + y1 * cost + this->y;
// 
//         vertexs[2].x = x2 * cost - y2 * sint + this->x;
//         vertexs[2].y = x2 * sint + y2 * cost + this->y;
// 
//         vertexs[3].x = x1 * cost - y2 * sint + this->x;
//         vertexs[3].y = x1 * sint + y2 * cost + this->y;
//     } else {
//         vertexs[0].x = x1 + this->x; vertexs[0].y = y1 + this->y;
//         vertexs[1].x = x2 + this->x; vertexs[1].y = y1 + this->y;
//         vertexs[2].x = x2 + this->x; vertexs[2].y = y2 + this->y;
//         vertexs[3].x = x1 + this->x; vertexs[3].y = y2 + this->y;
//     }
}




TextureCopyer::TextureCopyer() {

}

TextureCopyer::TextureCopyer(const TextureCopyer& copyer) {
    if (texture != nullptr) {
        texture->Release();
    }
    texture = copyer.texture;
    if (texture != nullptr) {
        texture->AddRef();
    }
}


TextureCopyer::~TextureCopyer() {
    free();
}


bool TextureCopyer::isValid() const {
    return texture != nullptr;
}


void TextureCopyer::free() {
//     if (texture != nullptr) {
//         texture->Release();
//         texture = nullptr;
//     }
    g_pD3D9App->freeTexture(texture);
}




bool BitmapD3D9::load(const char* truetype, int width, int height, uint color, bool shadow) {
    int texture_width = shadow ? (width + 1) : width;
    int texture_height = shadow ? (height + 1) : height;
    auto texture = (RGB888*)g_temp_memory;
    memset(texture, 0, sizeof(RGB888) * texture_width * texture_height);
    if (shadow) {
        for (int i = 0, j; i < height; ++i) {
            for (j = 0; j < width; ++j) {
                texture[(i + 1) * texture_width + (j + 1)]._ = truetype[i * width + j] ? 0xFF000000 : 0;
            }
        }
    }
    for (int i = 0, j; i < height; ++i) {
        for (j = 0; j < width; ++j) {
            texture[i * texture_width + j]._ = truetype[i * width + j] ? (0xFF000000 | color) : 0;
        }
    }
    return load(texture_width, texture_height, texture);
}


////////////////////////////////////////////////////////////////////////// 
bool BitmapD3D9::load(int width, int height, const RGB888* texture) {
    return load(width, height, 1, 1, texture);
}



bool BitmapD3D9::load(int width, int height, int row, int cel, const RGB888* datas) {
    free();
    this->width = width;
    this->height = height;
    this->row = row;
    this->cel = cel;
    texture = g_pD3D9App->createTexture(width * cel, height * row);
    if (!texture) {
        return false;
    }

    quad.setSize(width * cel, height * row);

    auto ptr = (uint*)g_pD3D9App->lockTexture(texture);
    memcpy(ptr, datas, width * cel * height * row * sizeof(RGB888));
    g_pD3D9App->unlockTexture(texture);

    return true;
}


bool BitmapD3D9::load(int width, int height, const uchar* indexs, const uchar* alphas, const RGB565* palatte) {
    int length = width * height;
    auto ptr = (RGB888*)g_temp_memory;
    // auto ptr = new RGB888[length];
    memset(ptr, 0, sizeof(RGB888) * length);
    auto p8 = ptr;
    auto p5 = palatte;
    auto index = indexs;
    auto alpha = alphas;
    for (int i = 0; i < length; ++i, ++p8, ++index, ++alpha) {
        if (*alpha == 0) {
            continue;
        }
        p5 = palatte + indexs[i];
        p8->a = (*alpha) << 3 | 7;
        p8->r = p5->r << 3;
        p8->g = p5->g << 2;
        p8->b = p5->b << 3;
    }
    auto ret = load(width, height, ptr);
    // delete[] ptr;
    return SUCCEEDED(ret);
}

void BitmapD3D9::render(int x, int y, float alpha /* = 1.0f */) const {
    quad.setXY(x, y);
    quad.setRect(0, 0, width, height);
    g_pD3D9App->renderQuad(&quad, texture);
}



void BitmapD3D9::render(int iframe, int x, int y, int x0, int y0, int width, int height, float alpha /*= 1.0f*/) const {
    quad.setXY(x, y);
    quad.setRect(x0 + (iframe % cel) * this->width, y0 + (iframe / cel) * this->height, width, height);
    g_pD3D9App->renderQuad(&quad, texture);
}




void BitmapD3D9::render1(int iframe, int x, int y, int width, int height) const {
    render(iframe, x, y, 0, 0, width, height);
}



void BitmapD3D9::render4(int x, int y, int x0, int y0, int width, int height) const {
    quad.setXY(x, y);
    quad.setRect(x0, y0, width, height);
    g_pD3D9App->renderQuad(&quad, texture);

}


void BitmapD3D9::render9(int x, int y, int width) const {
    int e = 16;
    width -= e;

    quad.setXY(x, y);
    quad.setRect(0, 0, width, height);
    g_pD3D9App->renderQuad(&quad, texture);


    quad.setXY(x + width, y);
    quad.setRect(this->width - e, 0, e, height);
    g_pD3D9App->renderQuad(&quad, texture);
}



void BitmapD3D9::render9(int x, int y, int width, int height, int e) const {
    width -= e;
    height -= e;

    quad.setXY(x, y);
    quad.setRect(0, 0, width, height);
    g_pD3D9App->renderQuad(&quad, texture);

    quad.setXY(x, y + height);
    quad.setRect(0, this->height - e, width, e);
    g_pD3D9App->renderQuad(&quad, texture);

    quad.setXY(x + width, y);
    quad.setRect(this->width - e, 0, e, height);
    g_pD3D9App->renderQuad(&quad, texture);

    quad.setXY(x + width, y + height);
    quad.setRect(this->width - e, this->height - e, e, e);
    g_pD3D9App->renderQuad(&quad, texture);
}
